//
//  NSDate+Extension.swift
//  zhengwutong
//
//  Created by wangshuguan on 16/8/24.
//  Copyright © 2016年 wangshuguan. All rights reserved.
//

import UIKit

extension Date {
    public struct Math {
        static var minute:TimeInterval = 60
        static var hour:TimeInterval = 3600
        static var day:TimeInterval = 86400
        static var week:TimeInterval = 604800
        static var year:TimeInterval = 31556926
    }
    var localizedDescription : String {
        get{
            var str = ""
            if self.isSameDay(Date()){
                str = DateFormatter(string: "今天 HH:mm").string(from: self)
            }else if self.isSameDay(Date.tomorrow){
                str = DateFormatter(string: "明天 HH:mm").string(from: self)
            }else if self.isSameDay(Date.tomorrow.tomorrow){
                str = DateFormatter(string: "后天 HH:mm").string(from: self)
            }else if abs(Date().timeIntervalSince(self)) < Math.year{
                str = DateFormatter.stringFromDate(date: self, formatter: "M月d日 HH:mm")
            }else{
                return DateFormatter.stringFromDate(date: self, formatter: "yy年M月d日 HH:mm")
            }
            return str
        }
    }
    var localized2Description : String {
        get{
            var str = ""
            let time = NSDate().timeIntervalSince(self)
            if abs(time) < Math.minute {
                str = "1分钟\(time>0 ? "前" : "后")"
            }else if abs(time) < Math.hour{
                let min:Int = {
                    if abs(time)/Math.minute<=0 {
                        return 1
                    }else{
                        return Int(abs(time)/Math.minute)
                    }
                }()
                str = "\(min)分钟\(time>0 ? "前" : "后")"
            }else if abs(time) < Math.day{
                let hour:Int = {
                    return Int(abs(time)/Math.hour)
                }()
                str = "\(hour)小时\(time>0 ? "前" : "后")"
            }else if abs(time) < Math.day*30{
                let day:Int = {
                    return Int(abs(time)/Math.day)
                }()
                str = "\(day)天\(time>0 ? "前" : "后")"
            }else if abs(time) < Math.year{
                str = DateFormatter.stringFromDate(date: self, formatter: "M月d日")
            }else{
                return DateFormatter.stringFromDate(date: self, formatter: "yy年M月d日")
            }
            return str
        }
    }
    var localized3Description : String {
        get{
            var str = ""
            let time = Date().timeIntervalSince(self)
            if abs(time) < Math.hour * 2 {
                str = "刚刚"
            }else if abs(time) < Math.day,self.isSameDay(Date()){
                str = self.hourMinDescription
            }else{
//                return DateFormatter.stringFromDate(date: self, formatter: "yy-MM-dd")
                return DateFormatter.stringFromDate(date: self, formatter: "yyyy/MM/dd")
            }
            return str
        }
    }
    var component:DateComponents{
        get{
            let zone = TimeZone.current
            let calendar = Calendar(identifier: .gregorian)
            return calendar.dateComponents(in: zone, from: self)
        }
    }
    /// "yyyy年MM月dd日 HH时mm分ss秒"
    var chineseDescription: String {
        get{
            return DateFormatter.chineseFormatter().string(from: self)
        }
    }
    /// "yyyy年MM月dd日"
    var simpleChineseDescription: String {
        get{
            return DateFormatter.simpleChineseFormatter().string(from: self)
        }
    }
    /// "yyyy-MM-dd"
    var simpleDescription: String {
        get{
            return DateFormatter.simpleFormatter().string(from: self)
        }
    }
    /// "HH:mm"
    var hourMinDescription:String{
        get{
            return DateFormatter.hourMinFormatter().string(from: self)
        }
    }
    /// "HH:mm aa"
    var hourMinADescription:String{
        get{
            return DateFormatter.hourMinAFormatter().string(from: self)
        }
    }
    /// "yyyy/MM/dd HH:mm:ss"
    var gangdateDescription:String{
        get{
            return DateFormatter.gangFormatter().string(from: self)
        }
    }
    /// "yyyy-MM-dd HH:mm:ss"
    var dateDescription:String{
        get{
            return DateFormatter.formatter().string(from: self)
        }
    }
    /// "yyyy-MM-dd HH:mm"
    var noSSDescription:String{
        get{
            return DateFormatter.noSSformatter().string(from: self)
        }
    }
    /// "yyyy年MM月dd日 HH:mm"
    var noSSChineseDescription:String{
        get{
            return DateFormatter.noSSChineseformatter().string(from: self)
        }
    }
    
    func description(string:String)->String{
        return DateFormatter.stringFromDate(date: self, formatter: string)
    }
}
extension Date{
    enum week : Int {
        case sunday = 1
        case monday = 2
        case tuesday = 3
        case wednesday = 4
        case thursday = 5
        case friday = 6
        case saturday = 7
        func description() -> String {
            switch self {
            case .sunday:
                return "日"
            case .monday:
                return "一"
            case .tuesday:
                return "二"
            case .wednesday:
                return "三"
            case .thursday:
                return "四"
            case .friday:
                return "五"
            default:
                return "六"
            }
        }
        func englishDescription() -> String {
            return ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][self.rawValue-1]
        }
        static func all() -> [week] {
            return [.sunday,.monday,.tuesday,.wednesday,.thursday,.friday,.saturday]
        }
    }
    var minute:Int{
        get{
            return self.component.minute ?? 0
        }
    }
    var hour:Int{
        get{
            return self.component.hour ?? 0
        }
    }
    var second:Int{
        get{
            return self.component.second ?? 0
        }
    }
    var month:Int{
        get{
            return self.component.month ?? 1
        }
    }
    var year:Int{
        get{
            return self.component.year ?? 0
        }
    }
    var day:Int{
        get{
            return self.component.day ?? 0
        }
    }
    var dayOfWeek:Date.week{
        get{
            return Date.week(rawValue: self.component.weekday ?? 1) ?? .sunday
        }
    }
}
extension Date{
    static var tomorrow:Date{
        return Date().tomorrow
    }
    static var yesterday:Date{
        return Date().yesterday
    }
    static var beginOfMinute:Date{
        return Date().beginOfMinute
    }
    static var beginOfHour:Date{
        return Date().beginOfHour
    }
    static var beginOfDay:Date{
        return Date().beginOfDay
    }
    static var beginOfMonth:Date{
        return Date().beginOfMonth
    }
    static var beginOfYear:Date{
        return Date().beginOfYear
    }
    static var nextMinute:Date{
        return Date().nextMinute
    }
    static var nextHour:Date{
        return Date().nextHour
    }
    static var nextMonth:Date{
        return Date().nextMonth
    }
    static var nextYear:Date{
        return Date().nextYear
    }
    
    var nextMinute:Date{
        get{
            return self.beginOfMinute.addingTimeInterval(Math.minute)
        }
    }
    var nextHour:Date{
        get{
            return self.beginOfHour.addingTimeInterval(Math.hour)
        }
    }
    var nextMonth:Date{
        get{
            var comp = DateComponents()
            comp.year = self.year
            if comp.month == 12 {
                comp.year = self.beginOfMonth.year+1
                if self.nextYear.beginOfYear.dayOfWeek != .sunday{
                    comp.yearForWeekOfYear = comp.year
                }
                comp.month = 1
            }else{
                comp.month = self.beginOfMonth.month+1
            }
            comp.day = self.day
            comp.hour = self.hour
            comp.minute = self.minute
            comp.second = self.second
            let date = Calendar(identifier: .gregorian).date(from: comp)
            if date == nil{
                ZWTPrint("crash date:\(comp)---\(#function)")
            }
            return date ?? Date()
        }
    }
    var nextYear:Date{
        get{
            var comp = DateComponents()
            comp.year = self.year+1
            comp.month = self.month
            comp.day = self.day
            comp.hour = self.hour
            comp.minute = self.minute
            comp.second = self.second
            let date = Calendar(identifier: .gregorian).date(from: comp)
            if date == nil{
                ZWTPrint("crash date:\(comp)---\(#function)")
            }
            return date ?? Date()
        }
    }
    func monthDateFrom(month:Int)->Date {
        var comp = DateComponents()
        comp.month = month
        comp.year = self.year
        comp.day = self.day
        let date = Calendar(identifier: .gregorian).date(from: comp)
        if date == nil{
            ZWTPrint("crash date:\(comp)---\(#function)")
        }
        return date ?? Date()
    }
    func monthDateFrom(year:Int)->Date {
        var comp = DateComponents()
        comp.year = year
        comp.month = self.month
        comp.day = self.day
        let date = Calendar(identifier: .gregorian).date(from: comp)
        if date == nil{
            ZWTPrint("crash date:\(comp)---\(#function)")
        }
        return date ?? Date()
    }
    var beginOfMinute:Date{
        get{
            var comp = DateComponents()
            comp.year = self.year
            comp.month = self.month
            comp.day = self.day
            comp.hour = self.hour
            comp.minute = self.minute
            comp.second = 0
            let date = Calendar(identifier: .gregorian).date(from: comp)
            if date == nil{
                ZWTPrint("crash date:\(comp)---\(#function)")
            }
            return date ?? Date()
        }
    }
    var beginOfHour:Date{
        get{
            var comp = DateComponents()
            comp.year = self.year
            comp.month = self.month
            comp.day = self.day
            comp.hour = self.hour
            comp.minute = 0
            comp.second = 0
            let date = Calendar(identifier: .gregorian).date(from: comp)
            if date == nil{
                ZWTPrint("crash date:\(comp)---\(#function)")
            }
            return date ?? Date()
        }
    }
    var beginOfDay:Date{
        get{
            var comp = DateComponents()
            comp.year = self.year
            comp.month = self.month
            comp.day = self.day
            comp.hour = 0
            comp.minute = 0
            comp.second = 0
            let date = Calendar(identifier: .gregorian).date(from: comp)
            if date == nil{
                ZWTPrint("crash date:\(comp)---\(#function)")
            }
            return date ?? Date()
        }
    }
    var beginOfWeek:Date{
        get{
            return day(after: -dayOfWeek.rawValue+1)
        }
    }
    var beginOfMonth:Date{
        get{
            var comp = DateComponents()
            comp.year = self.year
            comp.month = self.month
            comp.day = 1
            comp.hour = 0
            comp.minute = 0
            comp.second = 0
            let date = Calendar(identifier: .gregorian).date(from: comp)
            if date == nil{
                ZWTPrint("crash date:\(comp)---\(#function)")
            }
            return date ?? Date()
        }
    }
    var beginOfYear:Date{
        get{
            var comp = DateComponents()
            comp.year = self.year
            comp.month = 1
            comp.day = 1
            comp.hour = 0
            comp.minute = 0
            comp.second = 0
            let date = Calendar(identifier: .gregorian).date(from: comp)
            if date == nil{
                ZWTPrint("crash date:\(comp)---\(#function)")
            }
            return date ?? Date()
        }
    }
    var yesterday:Date{
        get{
            return day(after: -1)
        }
    }
    var tomorrow:Date{
        get{
            return day(after: 1)
        }
    }
    func day(after day:Int) -> Date {
        return self.addingTimeInterval(Math.day * Double(day))
    }
    func isSameYear(_ date:Date) -> Bool {
        return self.year == date.year
    }
    func isSameMonth(_ date:Date) -> Bool {
        return self.isSameYear(date) && self.month == date.month
    }
    func isSameDay(_ date:Date) -> Bool {
        return self.isSameMonth(date) && self.day == date.day
    }
    func isLater(_ date:Date) -> Bool {
        return self > date
    }
    func isEarlier(_ date:Date) -> Bool {
        return self < date
    }
}
extension Date{
    //农历
    var lunarComponent:DateComponents{
        get{
            return Calendar(identifier: .chinese).dateComponents(in: TimeZone.current, from: self)
        }
    }
    var lunarDay:String {
        get{
            return ["初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十",
                    "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十",
                    "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"][(self.lunarComponent.day ?? 1)-1]
        }
    }
    var lunarMonth:String{
        get{
            return ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月",
                    "九月", "十月", "冬月", "腊月"][(self.lunarComponent.month ?? 1)-1]
        }
    }
}

extension String{
    /// "yyyy年MM月dd日 HH时mm分ss秒"
    var chineseDate: Date? {
        get{
            return DateFormatter.chineseFormatter().date(from: self)
        }
    }
    
    /// "yyyy年MM月dd日"
    var simpleChineseDate: Date? {
        get{
            return DateFormatter.simpleChineseFormatter().date(from: self)
        }
    }
    
    /// "yyyy-MM-dd"
    var simpleDate: Date? {
        get{
            return DateFormatter.simpleFormatter().date(from: self)
        }
    }
    /// "HH-mm"
    var hourMinDate: Date?{
        get{
            return DateFormatter.hourMinFormatter().date(from: self)
        }
    }
    /// "yyyy/MM/dd HH:mm:ss"
    var gangDate: Date?{
        get{
            return DateFormatter.formatter().date(from: self)
        }
    }
    /// "yyyy-MM-dd HH:mm:ss"
    var date: Date?{
        get{
            return DateFormatter.formatter().date(from: self)
        }
    }
    /// "yyyy-MM-dd HH:mm"
    var noSSDate:Date?{
        get{
            return DateFormatter.noSSformatter().date(from: self)
        }
    }
    /// "yyyy年MM月dd日 HH:mm"
    var noSSChineseDate:Date?{
        get{
            return DateFormatter.noSSChineseformatter().date(from: self)
        }
    }
    func date(string:String)->Date{
        return DateFormatter.dateFromString(str: self, formatter: string)
    }
}
extension DateFormatter{
    public convenience init(string _formatter:String) {
        self.init()
        dateFormat = _formatter
    }
    static func chineseFormatter() -> DateFormatter {
        return DateFormatter(string: "yyyy年MM月dd日 HH时mm分ss秒")
    }
    static func simpleChineseFormatter() -> DateFormatter {
        return DateFormatter(string: "yyyy年MM月dd日")
    }
    static func simpleFormatter() -> DateFormatter {
        return DateFormatter(string: "yyyy-MM-dd")
    }
    static func hourMinFormatter() -> DateFormatter {
        return DateFormatter(string: "HH:mm")
    }
    static func hourMinAFormatter() -> DateFormatter {
        return DateFormatter(string: "HH:mm aa")
    }
    static func formatter() -> DateFormatter {
        return DateFormatter(string: "yyyy-MM-dd HH:mm:ss")
    }
    static func noSSformatter() -> DateFormatter {
        return DateFormatter(string: "yyyy-MM-dd HH:mm")
    }
    /// "yyyy年MM月dd日 HH:mm"
    static func noSSChineseformatter() -> DateFormatter {
        return DateFormatter(string: "yyyy年MM月dd日 HH:mm")
    }
    /// "yyyy/MM/dd HH:mm:ss"
    static func gangFormatter() -> DateFormatter {
        return DateFormatter(string: "yyyy/MM/dd HH:mm:ss")
    }
    static func stringFromDate(date:Date,formatter:String)->String{
        let f = DateFormatter(string: formatter)
        return f.string(from: date)
    }
    static func dateFromString(str:String,formatter:String)->Date{
        let f = DateFormatter(string: formatter)
        return f.date(from: str) ?? Date()
    }
}
extension Int{
    var toString:String{
        get{
            return "\(self)"
        }
    }
    var twoCharacterString:String{
        get{
            if self.toString.count<2{
                return ""
            }
            return ""
        }
    }
}
